﻿#ifndef DRIVER_STRUCT_H
#define DRIVER_STRUCT_H

/**
 * @file driverStruct.h
 * @brief 设备驱动程序相关的数据结构和类定义
 * @details 包含设备属性管理、端口掩码操作、设备枚举等核心功能
 */

#include <windows.h>
#include <SetupAPI.h>
#include <memory>
#include <string>
#include <functional>

#include <QString>

/**
 * @brief 设备参数变更结构体
 * @details 用于跟踪设备参数的变更状态
 */
struct ChangeDeviceParams {
    /**
     * @brief 构造函数
     * @param portName 物理端口名称
     * @param parameters 参数字符串
     */
    ChangeDeviceParams(const char* portName, const char* parameters)
        : physicalPortName(portName), parameters(parameters), hasChanged(false) {}

    const char* physicalPortName;  ///< 物理端口名称
    const char* parameters;        ///< 参数字符串
    bool hasChanged;               ///< 是否已变更标志
};

/**
 * @brief 设备属性管理类
 * @details 管理设备的ID、物理对象名称和位置信息，使用RAII原则管理内存
 */
class DeviceProperties {
public:
    /**
     * @brief 默认构造函数
     */
    DeviceProperties();

    /**
     * @brief 拷贝构造函数
     * @param other 要拷贝的对象
     */
    DeviceProperties(const DeviceProperties& other);

    /**
     * @brief 析构函数，自动释放内存
     */
    ~DeviceProperties();

    /**
     * @brief 赋值操作符
     * @param other 要赋值的对象
     * @return 当前对象的引用
     */
    DeviceProperties& operator=(const DeviceProperties& other);

    /**
     * @brief 设置设备ID
     * @param deviceId 设备ID字符串
     * @return 设置后的设备ID指针
     */
    void setDeviceId(const QString& deviceId);

    /**
     * @brief 设置物理对象名称
     * @param objectName 物理对象名称
     * @return 设置后的物理对象名称指针
     */
    void setPhysicalObjectName(const QString& objectName);

    /**
     * @brief 设置设备位置信息
     * @param location 位置信息字符串
     * @return 设置后的位置信息指针
     */
    void setLocation(const QString& location);

    /**
     * @brief 获取设备ID
     * @return 设备ID字符串
     */
    QString getDeviceId() const { return deviceId; }

    /**
     * @brief 获取物理对象名称
     * @return 物理对象名称字符串
     */
    QString getPhysicalObjectName() const { return physicalObjectName; }

    /**
     * @brief 获取设备位置信息
     * @return 位置信息字符串
     */
    QString getLocation() const { return location; }

    /**
     * @brief 检查是否为空
     * @return 如果所有属性都为空则返回true
     */
    bool isEmpty() const;

    /**
     * @brief 清空所有属性
     */
    void clear();

private:
    QString deviceId;           ///< 设备ID
    QString physicalObjectName; ///< 物理对象名称
    QString location;           ///< 设备位置信息
};

/// 设备属性常量指针类型定义
using ConstDevicePropertiesPtr = const DeviceProperties*;

/**
 * @brief 设备回调函数类型定义
 * @param deviceInfo 设备信息句柄
 * @param deviceInfoData 设备信息数据指针
 * @param deviceProperties 设备属性指针
 * @param userParam 用户参数
 * @return 处理成功返回true，否则返回false
 */
using DeviceCallback = std::function<bool(HDEVINFO deviceInfo,
                                         PSP_DEVINFO_DATA deviceInfoData,
                                         ConstDevicePropertiesPtr deviceProperties,
                                         bool* rebootRequired,
                                         void* userParam)>;

/**
 * @brief 设备枚举过滤器函数类型定义
 * @param hardwareId 硬件ID字符串
 * @return 如果设备应该被包含在枚举中返回true
 */
using DeviceEnumFilter = std::function<bool(const QString& hardwareId)>;

/**
 * @brief 端口占用状态掩码管理类
 * @details 使用位掩码高效管理大量端口的占用状态
 */
class PortBusyMask {
public:
    /**
     * @brief 默认构造函数
     */
    PortBusyMask();

    /**
     * @brief 析构函数，自动清理资源
     */
    ~PortBusyMask();

    /**
     * @brief 禁用拷贝构造函数
     */
    PortBusyMask(const PortBusyMask&) = delete;

    /**
     * @brief 禁用赋值操作符
     */
    PortBusyMask& operator=(const PortBusyMask&) = delete;

    /**
     * @brief 清空所有掩码数据
     */
    void clear();

    /**
     * @brief 添加端口号到忙碌列表
     * @param portNumber 端口号
     * @return 操作成功返回true
     */
    bool addBusyPort(int portNumber);

    /**
     * @brief 从忙碌列表中移除端口号
     * @param portNumber 端口号
     */
    void removeBusyPort(int portNumber);

    /**
     * @brief 检查端口是否空闲
     * @param portNumber 端口号
     * @return 端口空闲返回true，忙碌返回false
     */
    bool isPortFree(int portNumber) const;

    /**
     * @brief 获取第一个空闲端口号
     * @return 第一个空闲的端口号
     */
    int getFirstFreePort() const;

    /**
     * @brief 检查端口是否忙碌
     * @param portNumber 端口号
     * @return 端口忙碌返回true，空闲返回false
     */
    bool isPortBusy(int portNumber) const;

private:
    PBYTE pBusyMask;        ///< 端口忙碌状态位掩码
    SIZE_T maskLength;     ///< 掩码长度（字节数）
};

/**
 * @brief 栈元素类
 * @details 用于实现简单的栈数据结构
 */
class StackElement {
public:
    /**
     * @brief 构造函数
     * @param data 要存储的数据指针
     */
    explicit StackElement(void* data) : data(data), next(nullptr) {}

    void* data;  ///< 存储的数据指针

private:
    StackElement* next;  ///< 指向下一个元素的指针

    friend class SimpleStack;
};

/**
 * @brief 简单栈实现类
 * @details 提供基本的栈操作功能
 */
class SimpleStack {
public:
    /**
     * @brief 默认构造函数
     */
    SimpleStack() : top(nullptr) {}

    /**
     * @brief 析构函数，清理所有元素
     */
    ~SimpleStack();

    /**
     * @brief 禁用拷贝构造函数
     */
    SimpleStack(const SimpleStack&) = delete;

    /**
     * @brief 禁用赋值操作符
     */
    SimpleStack& operator=(const SimpleStack&) = delete;

    /**
     * @brief 压入元素到栈顶
     * @param element 要压入的元素
     * @return 操作成功返回true
     */
    bool push(StackElement* element);

    /**
     * @brief 弹出栈顶元素
     * @return 栈顶元素指针，栈为空时返回nullptr
     */
    StackElement* pop();

    /**
     * @brief 检查栈是否为空
     * @return 栈为空返回true
     */
    bool isEmpty() const { return top == nullptr; }

    /**
     * @brief 获取栈中元素数量
     * @return 元素数量
     */
    size_t size() const;

private:
    StackElement* top;  ///< 栈顶元素指针
};

/**
 * @brief 设备枚举参数结构体
 * @details 包含设备枚举过程中需要的所有参数
 */
struct DeviceEnumParams {
    /**
     * @brief 默认构造函数，初始化所有成员为默认值
     */
    DeviceEnumParams();

    ConstDevicePropertiesPtr targetProperties;  ///< 目标设备属性
    DeviceCallback callback;                    ///< 设备回调函数
    void* callbackParam;                       ///< 回调函数参数
    SimpleStack* deviceStack;                  ///< 设备栈指针
    int deviceCount;                           ///< 设备计数
    bool *rebootRequired;                     ///< 是否需要重启
};

/**
 * @brief 设备参数结构体
 * @details 包含单个设备的枚举参数和属性
 */
struct DeviceParams {
    /**
     * @brief 构造函数
     * @param enumParams 枚举参数指针
     */
    explicit DeviceParams(DeviceEnumParams* enumParams);

    DeviceEnumParams* enumParams;      ///< 枚举参数指针
    DeviceProperties deviceProperties; ///< 设备属性
};

/**
 * @brief 卸载设备结构体
 * @details 包含要卸载的端口组号及状态值
 */
struct RemoveDeviceParams {
    RemoveDeviceParams(int _num) : num(_num), res(IDCANCEL) {}
    int num;
    int res;
};

/**
 * @brief 设备处理例程函数类型定义
 * @param deviceInfo 设备信息句柄
 * @param deviceInfoData 设备信息数据指针
 * @param deviceParams 设备参数指针
 * @return 处理结果代码
 */
using DeviceRoutine = std::function<int(HDEVINFO deviceInfo,
                                       PSP_DEVINFO_DATA deviceInfoData,
                                       DeviceParams* deviceParams)>;

#endif // DRIVER_STRUCT_H
